﻿using CodeAngel.Domain;
using CodeAngel.Domain.Framework;
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;

namespace CodeAngel.Services
{
    /// <summary>
    /// Exposes an API for accessing and working with domain data.
    /// </summary>
    public class DomainDataService : IDomainDataService
    {
        #region GetNextFriendlyID

        /// <summary>
        /// Gets the next friendly id for the identified entity.
        /// </summary>
        public int GetNextFriendlyID(string entityName)
        {
            string ConnectionString = ConfigurationManager.ConnectionStrings["DomainDatabaseConnection"].ConnectionString;
            using (var ThisConnection = new SqlConnection(ConnectionString))
            {
                try
                {
                    ThisConnection.Open();

                    SqlCommand ThisCommand = new SqlCommand();
                    ThisCommand.Connection = ThisConnection;
                    ThisCommand.CommandType = CommandType.StoredProcedure;
                    ThisCommand.CommandText = "GetNextFriendlyID";

                    ThisCommand.Parameters.AddWithValue("@EntityName", entityName);
                    var NextFriendlyIdParameter = ThisCommand.Parameters.Add("@NextFriendlyID", SqlDbType.Int);
                    NextFriendlyIdParameter.Direction = ParameterDirection.Output;

                    ThisCommand.ExecuteNonQuery();
                    return Convert.ToInt32(NextFriendlyIdParameter.Value);
                }
                catch (Exception ex)
                {
                    throw new Exception("There was an unexpected problem geting the next friendly id for " + entityName, ex);
                }
                finally
                {
                    if (ThisConnection != null && ThisConnection.State != ConnectionState.Closed) ThisConnection.Close();
                }
            }
        }

        #endregion

        #region GetDtoHost

        /// <summary>
        /// Creates and returns a DtoHost object as dictated by the identified aggregate and filter.  The 
        /// passed in credentials are used to verify that the identified user has permission to access the data.
        /// </summary>
        public DtoHost GetDtoHost(string aggregateType, string filter, string userName, string password)
        {
            // Create an instance of the identified aggregate type.  This is the object that will create
            // desired DTO Host object.
            var ThisAggregate = Aggregate.CreateAggregate(aggregateType);

            // Return the populated DtoHost as dictated by the specific aggregate.
            return ThisAggregate.GetDtoHost(filter, userName, password);
        }

        #endregion

        #region Save

        /// <summary>
        /// Saves the data in the dtoHost object using the identified aggregate type.  The passed in
        /// credentials are used to verify that user has permission to modify the data.
        /// </summary>
        public DtoHost Save(string aggregateType, DtoHost dtoHost, string userName, string password)
        {
            // Create an instance of the identified aggregate type.  This is the object that knows
            // how to save the data in the dtoHost.
            var ThisAggregate = Aggregate.CreateAggregate(aggregateType);
            return ThisAggregate.SaveToDatabase(dtoHost, userName, password);
        }

        #endregion

        #region Delete

        /// <summary>
        /// Deletes an entity from the database.
        /// </summary>
        /// <param name="deleteAggregateType">The DeleteAggregate type - this must match the type of 
        /// the identified entity that will be deleted</param>
        /// <param name="id">The identification of the entity to be deleted</param>
        public void Delete(string deleteAggregateType, Guid id, string userName, string password)
        {
            // Create an instance of the identified aggregate type.  This is the object that knows
            // how to delete the identified entity.
            var ThisAggregate = DeleteAggregate.CreateAggregate(deleteAggregateType);
            ThisAggregate.DeleteFromDatabase(id, userName, password);
        }

        #endregion
    }
}
